interface IPerson {
  name: string;
  age: number;
  isSon: boolean;
}
type PT1 = Pick<IPerson, "age">;
interface IObject {
  [key: string]: any;
}
const obj: IObject = { name: "测试" };
type KeysType = ObjectKeyType<IPerson>; // string | number | boolean;

type ObjectKeyType<T> = T extends { [key in keyof T]: infer R } ? R : T;

// 注意：infet只能在 extends 子句中声明
// type T1<T extends (infer R)[]> =  T[0]; // 报错

// 注意：infer 声明的类型变量只能在 条件为true的分支上使用
// type T2<T> = T extends (infer R)[] ? T : R; // 报错
type T3<T> = T extends (infer R)[] ? R : T; // 不报错
type TrimLeft<T> = T extends infer R ? R : T; // 不报错

type MyFnReturnType<T> = T extends (...angs: any[]) => infer R ? R : T;

type MyAnyReturnType<T> = T extends (...angs: any[]) => infer R
  ? R
  : T extends Promise<infer U>
  ? U
  : T extends (infer K)[]
  ? K
  : T;

type F0 = MyAnyReturnType<() => number>;
type F1 = MyAnyReturnType<string>;
type F2 = MyAnyReturnType<Promise<string>>;
type F3 = MyAnyReturnType<string[]>;
type F4 = MyAnyReturnType<[number, string]>;
type F5 = MyAnyReturnType<number | string>;

type ProperType<T> = T extends { id: infer U; age: infer U } ? U : T;
type P1 = ProperType<{ id: string; age: number }>; // string | number

// 使用 Record 定义对象
type PT2 = Record<"name" | "test", IPerson>;
const pt2: PT2 = {
  name: { age: 0, isSon: true, name: "11" },
  test: { age: 0, isSon: true, name: "11" },
};
// 获取tuple类型中的第一个元素类型
type FirstType<T> = T extends [infer R, ...any[]] ? R : T;
type X1 = FirstType<[string, number]>;
type X2 = FirstType<["hello", number]>;
type X3 = FirstType<["hello" | "world", number]>;

// 判断tuple类型中的第一个元素类型是不是string类型,是就返回string不是就返回never
type FirstIsString<T> = T extends [infer R, ...any[]]
  ? R extends string
    ? R
    : never
  : never;
// 或者另一种写法
// infer 定义R 并且判断 R 是不是 string类型
type FirstIsStringType<T> = T extends [infer R extends string, ...any[]]
  ? R
  : never;

type Y1 = FirstIsString<[number]>;
type Y2 = FirstIsStringType<[number]>;

export {};
